/////////////////////////////////////////////////////////////////////////////
// Name:        ax_menu_shortcuts.cpp
// Purpose:     Shortcut settings menu class
// Author:      Julian Smart
// Modified by:
// Created:     2009-03-20
// RCS-ID:
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#include "wx/wx.h"

#include "ax/ax_menu_text.h"
#include "ax/ax_menu_shortcuts.h"
#include "ax/ax_menu_choice.h"
#include "ax/ax_menu_alert.h"
#include "ax/ax_speech.h"
#include "shortcutcust/shortcutcust.h"
#include "ax/ax_shortcutinputdialog.h"

/*
 * AxShortcutsMenuItem implementation.
 */

IMPLEMENT_CLASS( AxShortcutsMenuItem, AxMenuItem )

BEGIN_EVENT_TABLE( AxShortcutsMenuItem, AxMenuItem )
END_EVENT_TABLE()

AxShortcutsMenuItem::AxShortcutsMenuItem(AxMenuController* controller, AxSpeech* speech,
        wxShortcutManager* manager, wxWindow* window, wxMenuBar* menuBar)
{
    m_speech = speech;
    m_controller = controller;
    m_shortcutManager = manager;
    m_window = window;
    m_menuBar = menuBar;

    SetLabel(_("Shortcut Settings"));
    SetDescription(_("Lets you customize your shortcuts."));

    SetDynamic();

    AxShortcutsActivator* activator = new AxShortcutsActivator(speech, manager);
    activator->SetMenuItem(this);
    SetActivator(activator);
}

void AxShortcutsMenuItem::OnChangeShortcut(wxCommandEvent& WXUNUSED(event))
{
    // This causes shortcuts to stop working
    // m_shortcutManager->SetAcceleratorTable(m_window);
    if (m_menuBar)
        m_shortcutManager->UpdateMenuBar(m_menuBar);
}

void AxShortcutsMenuItem::UpdateShortcuts()
{
    size_t i;
    for (i = 0; i < GetSubMenu()->GetCount(); i++)
    {
        AxMenuItem* item = GetSubMenu()->GetItem(i);
        if (item->GetSubMenu())
        {
            size_t j;
            for (j = 0; j < item->GetSubMenu()->GetCount(); j++)
            {
                AxTextMenuItem* textItem = wxDynamicCast(item->GetSubMenu()->GetItem(j), AxTextMenuItem);
                if (textItem)
                {
                    wxShortcutItem* shortcutItem = m_shortcutManager->Find(textItem->GetId());
                    if (shortcutItem)
                    {
                        textItem->SetValue(m_shortcutManager->GetReadableShortcutString(* shortcutItem));
                    }
                }
            }
        }
    }
}

IMPLEMENT_DYNAMIC_CLASS( AxShortcutsActivator,  AxActivator )

// Called when the user activates a menu item by pressing return or double-clicking
AxMenu* AxShortcutsActivator::Activate(AxMenuController* WXUNUSED(controller), AxMenuItem* it)
{
    AxMenu* menu = new AxMenu;
    menu->SetLabel(_("Shortcut Settings"));
    menu->SetDescription(_("Lets you customize your shortcuts."));

    wxArrayString categories;

    size_t i;
    for (i = 0; i < (size_t) m_shortcutManager->GetCount(); i++)
    {
        wxShortcutItem* item = m_shortcutManager->GetNth(i);
        if (categories.Index(item->GetCategory()) == wxNOT_FOUND)
            categories.Add(item->GetCategory());
    }

    categories.Sort();
    size_t j;
    for (j = 0; j < categories.GetCount(); j++)
    {
        wxString category = categories[j];

        AxMenuItem* categoryItem = new AxMenuItem(
            category,
            category,
            category);
        AxMenu* categoryMenu = new AxMenu(category, category);

        for (i = 0; i < (size_t) m_shortcutManager->GetCount(); i++)
        {
            wxShortcutItem* item = m_shortcutManager->GetNth(i);
            if (item->GetCategory() == category)
            {
                wxString name = wxGetTranslation(item->GetName());

                AxTextMenuItem* menuItem = new AxTextMenuItem(
                    name + wxT(": ") + _("%VALUE%"),
                    _("Activate to edit this shortcut."),
                    name,
                    _("Enter Shortcut"),
                    _("Press alt, shift, control and alphabetic keys one at a time to change the shortcut. Then press Return to confirm or Escape to cancel. Shortcut for ") + name + wxT(":"),
                    m_shortcutManager->GetReadableShortcutString(* item));
                categoryMenu->AddItem(menuItem);
                
                menuItem->SetActivator(new AxShortcutTextActivator(AxShortcutTextActivator::AxShortcutCommandShortcut,
                    menuItem->GetLabel(),
                    menuItem->GetDescription(), m_shortcutManager, m_speech, item));
                
                menuItem->Connect(AxGetId(item->GetName()), wxEVT_COMMAND_TEXT_UPDATED,
                    wxCommandEventHandler(AxShortcutsMenuItem::OnChangeShortcut), NULL, it);
            }
        }
        categoryMenu->AddItem(new AxGoUpMenuItem);
        categoryItem->SetSubMenu(categoryMenu);
        menu->AddItem(categoryItem);
    }

    AxMenuItem* menuItem = new AxMenuItem(
        _("Reset shortcuts"),
        _("Resets the shortcuts to factory settings."),
        wxEmptyString);
    menuItem->SetActivator(new AxShortcutTextActivator(AxShortcutTextActivator::AxShortcutCommandReset,
        wxEmptyString,
        wxEmptyString, m_shortcutManager, m_speech, NULL));

    menu->AddItem(menuItem);
    
    menu->AddItem(new AxGoUpMenuItem);

    return menu;
}

/*
 * AxShortcutTextActivator implementation.
 * Sets the value of a boolean variable when toggled.
 */

IMPLEMENT_DYNAMIC_CLASS( AxShortcutTextActivator, AxTextActivator )

AxShortcutTextActivator::AxShortcutTextActivator(
        AxShortcutCommand command,
        const wxString& labelSpec,
        const wxString& descrSpec,
        wxShortcutManager* shortcutManager,
        AxSpeech* speech,
        wxShortcutItem* shortcut)
{
    Init();

    m_command = command;
    m_labelSpec = labelSpec;
    m_descriptionSpec = descrSpec;

    m_speech = speech;
    m_shortcutManager = shortcutManager;
    m_shortcut = shortcut;
}

void AxShortcutTextActivator::Init()
{
    m_speech = NULL;
    m_shortcutManager = NULL;
    m_shortcut = NULL;
}

void AxShortcutTextActivator::Copy(const AxShortcutTextActivator& activator)
{
    AxTextActivator::Copy(activator);

    m_speech = activator.m_speech;
    m_shortcutManager = activator.m_shortcutManager;
    m_shortcut = activator.m_shortcut;
}

AxMenu* AxShortcutTextActivator::Activate(AxMenuController* controller, AxMenuItem* item)
{
    if (m_command == AxShortcutCommandShortcut)
    {
        AxTextMenuItem* textItem = GetTextMenuItem();
        if (!textItem)
            return NULL;

        AxShortcutInputDialog dialog(NULL, textItem->GetMessage(), textItem->GetCaption(),
            * m_shortcut);
        dialog.SetShortcutManager(m_shortcutManager);
        dialog.SetSpeech(m_speech);
        if (dialog.ShowModal() == wxID_OK && ! ((*m_shortcut) == dialog.GetShortcut()))
        {
            * m_shortcut = dialog.GetShortcut();
            
            textItem->SetValue(m_shortcutManager->GetReadableShortcutString(* m_shortcut));
            textItem->SendTextUpdate(textItem->GetValue());
        }
    }
    else if (m_command == AxShortcutCommandReset)
    {
        wxArrayString labels, ids, descriptions;
        
        labels.Add(_("Choose this to reset the shortcuts"));
        
        ids.Add(wxT("RESET"));
        
        descriptions.Add(_("Select this if you wish to reset the shortcuts to factory settings."));
        
        AxModalChoiceMenu menu(controller, item,
            _("Reset shortcuts"),
            _("Please choose whether you wish to reset the shortcuts."),
            labels, ids, descriptions);
        wxString id = menu.ShowModal();
        
        if (id == wxT("RESET"))
        {
            m_shortcutManager->ResetShortcuts();

            AxShortcutsMenuItem* shortcutsItem = wxDynamicCast(item->GetParent()->GetParent(), AxShortcutsMenuItem);
            if (shortcutsItem)
            {
                //shortcutsItem->m_shortcutManager->SetAcceleratorTable(shortcutsItem->m_window);
                if (shortcutsItem->m_menuBar)
                    m_shortcutManager->UpdateMenuBar(shortcutsItem->m_menuBar);
                shortcutsItem->UpdateShortcuts();
            }

            AxModalAlertMenu alert(controller, item,
                _("Done!"),
                _("Shortcuts have been reset."),
                _("Shortcuts have been reset."));
            alert.ShowModal();
        }
    }

    return NULL;
}
